﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Evolution
{
    class Evolution
    {
        static void Main()
        {
            MatrixControl mc, mcNew;
            ConsoleKeyInfo cki;

            //size of matrix
            int mRows = 30;  
            int mColumns = 30;

            Console.SetWindowSize(40,40);
            Console.Title = "Homework #2: Evolution";

            mc=new MatrixControl(mRows,mColumns);
            mcNew = new MatrixControl(mRows, mColumns);
            mc.PrintMatrix();
            Console.WriteLine("");
            Console.WriteLine("Press <Spasebar> to simulate new state");
            Console.WriteLine("Press <Escape> to exit");
               
            do
            {
                cki = Console.ReadKey();

                switch (cki.Key)
                {
                    case ConsoleKey.Spacebar:
                                
                      for (int i=0; i<mColumns; i++)  
                        for (int j=0; j<mRows; j++)
                        {
                            int count = 0;

                            if ((i>0)&&(j>0))
                                if (mc.MatrixChar[i-1, j-1] == '*') count++;
                            if (i>0)
                                if (mc.MatrixChar[i-1, j] == '*') count++;
                            if ((i>0)&&(j<mRows-1))
                                if (mc.MatrixChar[i-1, j+1] == '*') count++;
                            if (j>0)
                                if (mc.MatrixChar[i, j-1] == '*') count++;
                            if (j<mRows-1)
                                if (mc.MatrixChar[i, j+1] == '*') count++;
                            if ((i<mColumns-1)&&(j>0))
                                if (mc.MatrixChar[i+1, j-1] == '*') count++;
                            if (i<mColumns-1)
                                if (mc.MatrixChar[i+1, j] == '*') count++;
                            if ((i<mColumns-1)&&(j<mRows-1))
                                if (mc.MatrixChar[i+1, j+1] == '*') count++;
                            
                            if (mc.MatrixChar[i, j] == '*')
                            {
                                if ((count == 8) ||
                                   ((count == 3) && (((i==0) && (j == 0)) ||
                                                     ((i == 0) && (j == mRows - 1)) ||
                                                     ((i == mColumns-1) && (j == 0)) ||
                                                     ((i == mColumns-1) && (j == mRows - 1)))) ||
                                   ((count == 5) && ((i == 0) || (i == mColumns-1) ||
                                                     (j == 0) || (j == mRows - 1))))
                                {
                                    mcNew.MatrixChar[i,j]=' ';
                                }
                            }
                            else 
                            if (count>1) mcNew.MatrixChar[i,j]='*';        
                        }

                        Console.Clear();
                        mcNew.PrintMatrix();
                        Console.WriteLine("");
                        Console.WriteLine("Press <Spasebar> to simulate new state");
                        Console.WriteLine("Press <Escape> to exit");
                        for (int i = 0; i < mColumns; i++)
                          for (int j = 0; j < mRows; j++)
                          {
                              mc.MatrixChar[i, j] = mcNew.MatrixChar[i, j];
                          }
                        break;
                    default:
                        //Console.Write(" ");
                        break;
                    }
                } while (cki.Key != ConsoleKey.Escape);
        }
    }

    class MatrixControl
    {
        char[,] matrixChar;
        byte[,] matrixByte;

        /// <summary>
        /// The property which give an access to private field matrixChar
        /// </summary>
        public char[,] MatrixChar
        {
            get
            {
                return matrixChar;
            }
            set
            {
                matrixChar = value;
            }
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="rows">Quantity of matrix rows</param>
        /// <param name="columns">Quantity of matrix columns</param>
        public MatrixControl(int rows, int columns)
        {
            matrixChar = new char[rows,columns]; 
            matrixByte = new byte[rows, columns];

            Random randomizer = new Random();
            for (int i = 0; i < matrixByte.GetLength(0); i++)
            {
                for (int j = 0; j < matrixByte.GetLength(1); j++)
                {
                    matrixByte[i, j] = (byte)randomizer.Next(0,2);
                    if (matrixByte[i, j] == 1)
                    {
                        matrixChar[i, j] = '*';
                    }
                    else matrixChar[i,j]=' ';
                }
            }

        }
       
        /// <summary>
        /// The method which print the matrix into console window
        /// </summary>
        public void PrintMatrix()
        {
            for (int j = 0; j < matrixChar.GetLength(0); j++)
            {
                for (int i = 0; i < matrixChar.GetLength(1); i++)
                    Console.Write(matrixChar[j,i]);
                Console.WriteLine();
            }
        }
    }
}
